﻿/**
 * 功能简介：
 * （1）操作简便、友好的系统界面；
 * （2）设置运行密码：让软件只允许您一人使用。
 * （3）可以点对点进行文件传输；
 * （4）有断点续传的
 * （5）对传输的文件进行加密，进行数字签名；
 * （6）对接收的文件进行解密；
 * （7）提供传输双方的即时交流沟通；（如果用对称密码加密协商密钥）
 * （8）提供传输日志的查阅。
 */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Security;
using System.Security.Cryptography;


namespace httpd_client
{

    public partial class Form_Main : Form
    {
        public delegate void CloseFather();//声明一个委托

        public CloseFather close_father; //定义委托

        private String log_file = "log.log";

        public static String local_ip;
        public static int local_listen_port = 10240;

        private Thread bg_thread;

        public static Mutex tcp_in_mutex;
        public static Mutex tcp_out_mutex;
        public static Mutex status_mutex;

        public static Queue<thrd_comm_entry_t> tcp_inlist;
        public static Queue<thrd_comm_entry_t> tcp_outlist;
        public static Queue<thrd_comm_entry_t> status_inlist;

        private String path_program;
        private String path_temp;


        public Form_Main()
        {
            InitializeComponent();

            tcp_inlist = new Queue<thrd_comm_entry_t>();
            status_inlist = new Queue<thrd_comm_entry_t>();
            tcp_in_mutex = new Mutex();
            tcp_outlist = new Queue<thrd_comm_entry_t>();
            tcp_out_mutex = new Mutex();
            status_mutex = new Mutex();

            bg_thread = new Thread(new ThreadStart(bg_work));
            bg_thread.Start();

            IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
            IPAddress ipAddress;
            for (int i = 0; i != ipHostInfo.AddressList.Length; i++)
            {
                if (!ipHostInfo.AddressList[i].IsIPv6LinkLocal)
                {
                    ipAddress = ipHostInfo.AddressList[i];
                    local_ip = ipAddress.ToString();
                    if (local_ip.IndexOf("169.254") >= 0)
                    {
                        continue;
                    }
                    break;
                }
            }


            path_program = System.AppDomain.CurrentDomain.BaseDirectory;
            path_temp = path_program + "Temp";
        }

        /**
         * 增加一条log
         */
        private void log_add(String log)
        {
            String s = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + ":" + log + "\r\n";
            rtb_log.AppendText(s);
            File.AppendAllText(log_file, s);
        }

        /** ************************************************************************************************************
         * 主窗体控件
         ************************************************************************************************************ */


        private void tb_ip_TextChanged(object sender, EventArgs e)
        {
            tb_ip.Text = tb_ip.Text.Trim();
        }

        private void btn_conn_Click(object sender, EventArgs e)
        {
            String server;
            int port = 10240, pos;

            pos = tb_ip.Text.Trim().IndexOf(":");
            server = tb_ip.Text.Trim().Remove(pos);
            port = Convert.ToInt32(tb_ip.Text.Trim().Substring(pos + 1), 10);
            System.Text.RegularExpressions.Regex check = new System.Text.RegularExpressions.Regex(@"^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$");
            if (!check.IsMatch(server))
            {
                MessageBox.Show("请输入正确的IP地址。");
            }
            else if(btn_conn.Text == "连接")
            {
                tb_ip.ReadOnly = true;
                btn_conn.Enabled = false;
                thrd_comm_entry_t item = new thrd_comm_entry_t();
                item.data_buf = Encoding.UTF8.GetBytes(server + ":" + port);
                item.data_size = (UInt32)(server + ":" + port).Length;
                item.dir = task_dir_t.DIR_REQUEST;
                item.type = task_type_t.TYP_CONNECT_TO_SERV;
                tcp_out_mutex.WaitOne();
                tcp_outlist.Enqueue(item);
                tcp_out_mutex.ReleaseMutex();
            }
            else if (btn_conn.Text == "断开连接")
            {
                tb_ip.ReadOnly = true;
                btn_conn.Enabled = false;
                thrd_comm_entry_t item = new thrd_comm_entry_t();
                item.data_buf = Encoding.UTF8.GetBytes(server + ":" + port);
                item.data_size = (UInt32)(server + ":" + port).Length;
                item.dir = task_dir_t.DIR_NO_RESPONSE;
                item.type = task_type_t.TYP_DISCONNECT_TO_SERV;
                tcp_out_mutex.WaitOne();
                tcp_outlist.Enqueue(item);
                tcp_out_mutex.ReleaseMutex();
            }
        }


        private void Form_Main_FormClosed(object sender, FormClosedEventArgs e)
        {
            bg_thread.Abort();
        }

        /**
         * 定时接收客户端和服务端返回了消息
         */
        private void tim_main_Tick(object sender, EventArgs e)
        {

            thrd_comm_entry_t item = null;
            String log;

            /*
             * 状态队列
             */
            while (status_inlist.Count != 0)
            {
                status_mutex.WaitOne();
                if (status_inlist.Count != 0)
                {
                    item = null;
                    item = status_inlist.Dequeue();
                }
                status_mutex.ReleaseMutex();
                if (item == null)
                {
                    break;
                }
                else
                {
                    switch (item.type)
                    {
                        case task_type_t.TYP_CONNECT_TO_SERV:
                            if (item.status == 0)
                            {
                                btn_conn.Enabled = true;
                                btn_conn.Text = "断开连接";
                                log = "与服务器"+tb_ip.Text+"连接成功。";
                                log_add(log);
                                btn_getlog.Enabled = true;
                              
                            }
                            break;
                        case task_type_t.TYP_LOG:
                            log = Encoding.UTF8.GetString(item.data_buf, 0, (int)item.data_size);
                            log_add(log);
                            break;
                        case task_type_t.TYP_DISCONNECT_TO_SERV:
                            if (item.status == 0)
                            {
                                btn_conn.Enabled = true;
                                btn_getlog.Enabled = false;
                               
                                btn_conn.Text = "连接";
                                log = "与服务器" + tb_ip.Text + "连接断开。";
                                log_add(log);

                            }
                            break;
                        default:
                            break;
                    }
                }
            }


        }

        private void btn_getlog_Click(object sender, EventArgs e)
        {
            thrd_comm_entry_t item = new thrd_comm_entry_t();
            item.data_size = 1;
            item.data_buf[0] = 1;
            item.dir = task_dir_t.DIR_REQUEST;
            item.type = task_type_t.TYP_LOG_SEND_TO_REMOTE;
            tcp_out_mutex.WaitOne();
            tcp_outlist.Enqueue(item);
            tcp_out_mutex.ReleaseMutex();
            btn_getlog.Enabled = false;
            btn_sotplog.Enabled = true;
        }

        private void btn_sotplog_Click(object sender, EventArgs e)
        {
            thrd_comm_entry_t item = new thrd_comm_entry_t();
            item.data_size = 1;
            item.data_buf[0] = 0;
            item.dir = task_dir_t.DIR_REQUEST;
            item.type = task_type_t.TYP_LOG_SEND_TO_REMOTE;
            tcp_out_mutex.WaitOne();
            tcp_outlist.Enqueue(item);
            tcp_out_mutex.ReleaseMutex();
            btn_getlog.Enabled = true;
            btn_sotplog.Enabled = false;
        }

        private void btn_serv_quit_Click(object sender, EventArgs e)
        {
            thrd_comm_entry_t item = new thrd_comm_entry_t();
            item.data_size = 0;
            item.dir = task_dir_t.DIR_REQUEST;
            item.type = task_type_t.TYP_SERV_QUIT;
            tcp_out_mutex.WaitOne();
            tcp_outlist.Enqueue(item);
            tcp_out_mutex.ReleaseMutex();
            btn_getlog.Enabled = true;
            btn_sotplog.Enabled = false;
        }

        private void btn_logclr_Click(object sender, EventArgs e)
        {
            rtb_log.Clear();
        }
    }
}
